package com.zhu.classfile;

import com.zhu.classfile.attribute.AttributeInfo;
import com.zhu.classfile.attribute.CodeAttribute;
import com.zhu.classfile.attribute.ConstantValueAttribute;
import com.zhu.classfile.attribute.factory.AttributeInfoFactory;
import com.zhu.classfile.constant.ConstantPool;

import java.nio.ByteBuffer;

/**
 * 字段和方法都有这四个东西！
 * public String name;
 * public void sayHello() { ... }
 * {
 *     access_flags:      0x0001 (public)
 *     name_index:        2        → 指向常量池第 2 项 "name"
 *     descriptor_index:  3        → 指向常量池第 3 项 "Ljava/lang/String;"
 *     attributes:        []       → 字段可能没有属性，或有 ConstantValue
 * }
 * {
 *     access_flags:      0x0001 (public)
 *     name_index:        4        → 指向常量池第 4 项 "sayHello"
 *     descriptor_index:  5        → 指向常量池第 5 项 "()V"
 *     attributes:        [ ... ]  → 方法有 Code 属性，里面是字节码
 * }
 */
public class MemberInfo {

    private ConstantPool constantPool;
    protected  int accessFlags;
    protected  int nameIndex;
    protected  int descriptorIndex;
    protected  AttributeInfo[] attributes;

    public MemberInfo(int af, int ni, int di, AttributeInfo[] attrs,ConstantPool constantPool) {
        this.accessFlags = af;
        this.nameIndex = ni;
        this.descriptorIndex = di;
        this.attributes = attrs;
        this.constantPool=constantPool;
    }

    public static MemberInfo[] readMemberInfos(ByteBuffer buffer,int memberCounts,ConstantPool constantPool){
        MemberInfo[] memberInfos = new MemberInfo[memberCounts];
        for (int i=0;i<memberCounts;i++){
            int accessFlags = Short.toUnsignedInt(buffer.getShort());
            int nameIndex = Short.toUnsignedInt(buffer.getShort());
            int descriptorIndex = Short.toUnsignedInt(buffer.getShort());
            //属性的个数
            int attributesCount = Short.toUnsignedInt(buffer.getShort());
            AttributeInfo[] attributes = AttributeInfoFactory.readAttributes(buffer, constantPool,attributesCount);
            memberInfos[i]=new MemberInfo(accessFlags,nameIndex,descriptorIndex,attributes,constantPool);
        }
        return memberInfos;
    }

    public int getAccessFlags() {
        return accessFlags;
    }

    public String getName() {
        return constantPool.getUtf8(nameIndex);
    }

    public String getDescriptor() {
        return constantPool.getUtf8(descriptorIndex);
    }


    /**
     * 从 attributes 数组中查找 ConstantValue 属性。
     *
     * 只有被 static final 修饰的基本类型（如 int, long, double, String）字段
     * 才可能拥有 ConstantValue 属性。该属性不包含实际的常量值，而是指向
     * 常量池中某个常量项的索引。
     *
     * @return 找到的 ConstantValueAttribute，若无则返回 null
     */
    public ConstantValueAttribute getConstantValueAttribute() {
        for (AttributeInfo attr : attributes) {
            if (attr instanceof ConstantValueAttribute) {
                return (ConstantValueAttribute) attr;
            }
        }
        return null;
    }
    /**
     * 从 attributes 数组中查找 Code 属性。
     * 只有非 native、非 abstract 方法才有 Code 属性。
     *
     * @return 找到的 CodeAttribute，若无则返回 null
     */
    public CodeAttribute getCodeAttribute() {
        for (AttributeInfo attr : attributes) {
            if (attr instanceof CodeAttribute) {
                return (CodeAttribute) attr;
            }
        }
        return null;
    }
}
